home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
sozobon2.zoo
/
hcc
/
gunk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-14
|
16KB
|
942 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* gunk.c
*
* Transformations on expression trees
* Most of this stuff is because we cant handle
* floats, long mul/div, or fields directly.
*/
#include <stdio.h>
#include "param.h"
#include "bstok.h"
#include "tytok.h"
#include "flags.h"
#include "nodes.h"
#include "gen.h"
NODEP copyone();
#define gwiden(x) ((x)==1 ? 2 : (x))
#define isfield(np) ((np)->g_token == '.' && (np)->g_fldw)
NODEP npar1, npar2, npar3;
char *spar1, *spar2, *spar3;
int ipar1, ipar2, ipar3;
struct rule {
int (*match)(); /* test for transformation needed */
int (*rewri)(); /* rewrite function */
};
int m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
int m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
int m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
struct rule gunktbl[] = {
{m_unfold, unfold},
{m_cast, cast},
{m_md_shf, md_shf},
{m_eident, eident},
{m_incdec, incdec},
{m_hardas, hardas},
{m_inline, inline}, /* must cast before inline */
{m_fcmp, fcmp},
{m_fldas, fldas},
{0}
};
int anygunk;
gunk(np)
NODEP np;
{
do {
anygunk = 0;
gunks(np);
} while (anygunk);
}
gunks(np)
register NODEP np;
{
switch (np->g_type) {
case E_BIN:
gunks(np->n_right);
case E_UNARY:
gunks(np->n_left);
}
gunk1(np);
}
gunk1(np)
NODEP np;
{
register struct rule *p;
for (p=gunktbl; p->match; p++)
if ((*p->match)(np)) {
anygunk++;
(*p->rewri)(np);
return;
}
}
/*
* Change pointer arithmetic to equivalent trees
* (main thing is to mult or div by object size)
*/
m_unfold(np)
NODEP np;
{
switch (np->g_token) {
case PTRADD:
ipar1 = '+';
return 1;
case PTRSUB:
ipar1 = '-';
return 1;
case PTRDIFF:
ipar1 = 0;
return 1;
case ASSIGN PTRADD:
ipar1 = ASSIGN '+';
return 1;
case ASSIGN PTRSUB:
ipar1 = ASSIGN '-';
return 1;
}
return 0;
}
unfold(np)
NODEP np;
{
if (ipar1) {
ins_mul(np, np->g_offs);
np->g_token = ipar1;
} else {
ins_div(np, np->g_offs);
}
}
NODEP
newgcon(kon, ty, sz)
long kon;
{
register NODEP kp;
kp = allocnode();
kp->g_token = ICON;
sprintf(kp->n_name, "%ld", kon);
kp->g_offs = kon;
kp->g_type = E_LEAF;
kp->g_ty = ty;
kp->g_sz = sz;
return kp;
}
ins_mul(np, kon)
NODEP np;
long kon;
{
NODEP rp = np->n_right;
register NODEP mp, kp;
if (kon == 1)
return;
if (rp->g_token == ICON) {
rp->g_offs *= kon;
rp->g_sz = gwiden(rp->g_sz);
return;
}
mp = allocnode();
mp->g_token = '*';
sprintf(mp->n_name, "p*");
mp->g_type = E_BIN;
mp->g_ty = rp->g_ty;
mp->g_sz = gwiden(rp->g_sz);
kp = newgcon(kon, mp->g_ty, mp->g_sz);
mp->n_right = kp;
mp->n_left = np->n_right;
np->n_right = mp;
}
ins_div(np, kon)
register NODEP np;
long kon;
{
register NODEP tp, kp;
kp = newgcon(kon, np->g_ty, np->g_sz);
tp = copyone(np);
tp->g_token = '-';
tp->n_left = np->n_left;
tp->n_right = np->n_right;
tp->g_sz = SIZE_P;
tp->g_ty = ET_U;
np->n_left = tp;
np->n_right = kp;
np->g_type = E_BIN;
np->g_token = '/';
sprintf(np->n_name, "p/");
}
#define CAST_LN 1
#define CAST_RN 2
#define CAST_LLONG 3
/*
* Insert needed (implied) casts
*/
m_cast(np)
NODEP np;
{
NODEP lp = np->n_left;
switch (np->g_type) {
case E_LEAF:
return 0;
case E_BIN:
return bm_cast(np);
}
/* must be unary */
switch (np->g_token) {
case UNARY '-':
case '~':
return castup(lp, np, CAST_LN);
case TCONV:
return fcastlong(np);
}
return 0;
}
bm_cast(np)
register NODEP np;
{
NODEP lp = np->n_left, rp = np->n_right;
if (isassign(np->g_token)) {
if (castup(rp, lp, CAST_RN))
return 1;
if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
return 1;
return 0;
}
switch (np->g_token) {
case '=':
if (np->g_ty == ET_A)
return 0;
return castany(rp, lp, CAST_RN);
case '<':
case '>':
case DOUBLE '=':
case NOTEQ:
case LTEQ:
case GTEQ:
if (castup(lp, rp, CAST_LN))
return 1;
return castup(rp, lp, CAST_RN);
case '(':
case ',':
case '?':
case DOUBLE '&':
case DOUBLE '|':
return 0;
case DOUBLE '<':
case DOUBLE '>':
if (castup(lp, np, CAST_LN))
return 1;
return castany(rp, np, CAST_RN);
default:
if (castup(lp, np, CAST_LN))
return 1;
return castup(rp, np, CAST_RN);
}
return 0;
}
fcastlong(np)
NODEP np;
{
NODEP lp = np->n_left;
if (red_con(lp))
return 0;
if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
ipar1 = CAST_LLONG;
return 1;
}
if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
ipar1 = CAST_LLONG;
return 1;
}
return 0;
}
castup(lowp, hip, par)
NODEP lowp, hip;
{
if (stronger(hip, lowp)) {
ipar1 = par;
npar1 = hip;
return 1;
}
return 0;
}
castmagic(p1, p2, par, tok)
NODEP p1, p2;
{
if (xstronger(p1,p2) && magicop(tok)) {
ipar1 = par;
npar1 = p2;
return 1;
}
return 0;
}
castany(p1, p2, par)
NODEP p1, p2;
{
if (p1->g_sz != p2->g_sz ||
((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
ipar1 = par;
npar1 = p2;
return 1;
}
return 0;
}
cast(np)
NODEP np;
{
switch (ipar1) {
case CAST_LN:
castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
break;
case CAST_RN:
castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
break;
case CAST_LLONG:
castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
break;
}
}
castsub(ty, sz, npp, np)
NODEP *npp, np;
{
register NODEP tp;
/* ICON cast optimization */
if (np->g_token == ICON &&
np->g_ty == ty &&
np->g_sz < sz) {
np->g_sz = sz;
return;
}
tp = allocnode();
tp->g_token = TCONV;
strcpy(tp->n_name, "cast up");
tp->n_left = np;
*npp = tp;
tp->g_sz = sz;
tp->g_ty = ty;
tp->g_type = E_UNARY;
}
/*
* Change stuff computer cant do to calls to inline functions
* (in this case, all floats and long *%/)
*/
m_inline(np)
NODEP np;
{
int isfloat, isuns;
if (np->g_type == E_LEAF)
return 0;
if (np->g_ty == ET_A)
return 0;
isfloat = (np->g_ty == ET_F);
isuns = (np->g_ty == ET_U);
if (np->g_type == E_UNARY) {
switch (np->g_token) {
case UNARY '-':
if (!isfloat) return 0;
spar1 = "%fpneg";
return 1;
case TCONV:
if ((np->n_left->g_ty == ET_F) == isfloat)
return 0;
if (red_con(np->n_left))
return 0;
spar1 = isfloat ? "fpltof" : "fpftol";
return 1;
}
return 0;
}
if (np->g_sz != 4) /* longs or floats only */
return 0;
switch (np->g_token) {
case '*':
spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
return 1;
case '/':
spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
return 1;
case '+':
if (!isfloat) return 0;
spar1 = "%fpadd";
return 1;
case '-':
if (!isfloat) return 0;
spar1 = "%fpsub";
return 1;
case '%':
spar1 = isuns ? "%lremu" : "%lrem";
return 1;
}
return 0;
}
inline(np)
NODEP np;
{
register NODEP nmp, cmap;
int isunary;
isunary = (np->g_type == E_UNARY);
if (isunary) {
np->n_right = np->n_left;
np->g_type = E_BIN;
} else {
cmap = copyone(np);
cmap->n_left = np->n_left;
cmap->n_right = np->n_right;
np->n_right = cmap;
cmap->g_token = ',';
cmap->g_offs = 2;
strcpy(cmap->n_name, ",inl");
}
nmp = allocnode();
np->n_left = nmp;
np->g_token = '(';
strcpy(np->n_name, "inline");
nmp->g_token = ID;
strcpy(nmp->n_name, spar1);
#ifdef OUT_AZ
strcat(nmp->n_name, "